# required libraries
library("RStoolbox")
library("raster")
library("rgdal")
library("ggplot2")
library("SDMTools")
# load tif using stack function instead raster
ortho_p3.stack <- stack("../6_qgis/output/orthomosaic_parcela3_photoscan_georreferenced.tif")
class(ortho_p3.stack)
# load parcela 1
library(rgeos)
parcelas <- readOGR("../6_qgis/input/alamala.kml", "alamala")[0]
nrowdim <- dim(parcelas@data)
parcelas@data$id <- c(rep(1:nrowdim))
parcela3 <- subset(parcelas, parcelas@data$id %in% c(9,10, 11, 12))
p3.centroid.df <- as.data.frame(gCentroid(parcela3, byid = TRUE)) # extract to label parcels
class(parcela3)
plot(parcela3)
parcela3.df <- fortify(parcela3) # to plot with ggplot
Regions defined for each Polygons
head(parcela3.df)
# Set all pixels to NA, where bands are 0 (remove black background)
# Check if results are affected
# instead use crop and mask together (ver más adelante)
ortho_p3.stack[ortho_p3.stack[,] == 0] <- NA
# plot scene using ggRGB (from ggplot and RStoolbox)
ggRGB(ortho_p3.stack, r = 1, g = 2, b = 3, maxpixels = 2e+05, stretch="none", geom_raster = TRUE) +
geom_path(data = parcela3.df, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
geom_text(data = p3.centroid.df, aes(label = c("3.1", "3.2", "3.3", "3.4") ,y = y, x = x + 0.0002), colour = "white") +
coord_equal() +
theme_bw()

ggsave("figures/parcela3.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
Extraemos las parcelas
# crop and mask whole area
ortho_p3.stack_p3 <- crop(mask(ortho_p3.stack, parcela3),parcela3)
# crop parcela 3.1
parcela31 <- subset(parcelas, parcelas@data$id %in% c(9))
ortho_p3.stack_p31 <- crop(mask(ortho_p3.stack_p3, parcela31), parcela31)
# crop parcela 1.2
parcela32 <- subset(parcelas, parcelas@data$id %in% c(10))
ortho_p3.stack_p32 <- crop(mask(ortho_p3.stack_p3, parcela32), parcela32)
# crop parcela 1.2
parcela33 <- subset(parcelas, parcelas@data$id %in% c(11))
ortho_p3.stack_p33 <- crop(mask(ortho_p3.stack_p3, parcela33), parcela33)
# crop parcela 1.2
parcela34 <- subset(parcelas, parcelas@data$id %in% c(12))
ortho_p3.stack_p34 <- crop(mask(ortho_p3.stack_p3, parcela34), parcela34)
Plot parcels
ggRGB(ortho_p3.stack_p3, r = 1, g = 2, b = 3) +
geom_path(data = parcela3.df, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
theme_bw()

Plot parcel 3.1
p31 <- subset(parcela3.df, id == 8)
ggRGB(ortho_p3.stack_p31, r = 1, g = 2, b = 3) +
geom_path(data = p31, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
labs(x="", y="", title="Parcela 3.1") +
# coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5)) # make title bold and add spac

ggsave("figures/parcela3_1.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
ggRGB(ortho_p3.stack, r = 1, g = 2, b = 3) +
geom_path(data = p31, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
labs(x="", y="", title="Parcela 3.1") +
# coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5)) # make title bold and add spac

ggsave("figures/parcela3_1_ortho.pdf",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
Plot parcel 3.2
p32 <- subset(parcela3.df, id == 9)
ggRGB(ortho_p3.stack_p32, r = 1, g = 2, b = 3) +
geom_path(data = p32, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
labs(x="", y="", title="Parcela 3.2") +
# coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5)) # make title bold and add spac

ggsave("figures/parcela3_2.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
ggRGB(ortho_p3.stack, r = 1, g = 2, b = 3) +
geom_path(data = p32, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
labs(x="", y="", title="Parcela 3.2") +
# coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5)) # make title bold and add spac

ggsave("figures/parcela3_2_ortho.pdf",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
Plot parcel 3.3
p33 <- subset(parcela3.df, id == 10)
ggRGB(ortho_p3.stack_p33, r = 1, g = 2, b = 3) +
geom_path(data = p33, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
labs(x="", y="", title="Parcela 3.3") +
# coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5)) # make title bold and add spac

ggsave("figures/parcela3_3.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
ggRGB(ortho_p3.stack, r = 1, g = 2, b = 3) +
geom_path(data = p33, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
labs(x="", y="", title="Parcela 3.2") +
# coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5)) # make title bold and add spac

ggsave("figures/parcela3_3_ortho.pdf",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
Plot parcel 3.4
p34 <- subset(parcela3.df, id == 11)
ggRGB(ortho_p3.stack_p34, r = 1, g = 2, b = 3) +
geom_path(data = p34, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
labs(x="", y="", title="Parcela 3.4") +
# coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5)) # make title bold and add spac

ggsave("figures/parcela3_4.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
ggRGB(ortho_p3.stack, r = 1, g = 2, b = 3) +
geom_path(data = p34, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
labs(x="", y="", title="Parcela 3.4") +
# coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5)) # make title bold and add spac

ggsave("figures/parcela3_4_ortho.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
Calculate VIs
p31.VIs <- spectralIndices(ortho_p3.stack_p31, green = 3, red=2, nir =1, indices=c("NDVI", "MSAVI2", "GNDVI"))
breaks <- seq(0, 1, by=0.01)
plot(p31.VIs)

Plot VI one by one
NDVI Parcela 3.1
cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p31.VIs$NDVI, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.1") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

And save
ggsave("figures/parcela3_1_NDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
MSAVI2 Parcela 3.1
cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p31.VIs$MSAVI2, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.1") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

And save
ggsave("figures/parcela3_1_MSAVI2.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
GNDVI Parcela 1.1
ggR(p31.VIs$GNDVI, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.1") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela3_1_GNDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
p32.VIs <- spectralIndices(ortho_p3.stack_p32, green = 3, red=2, nir =1, indices=c("NDVI", "MSAVI2", "GNDVI"))
breaks <- seq(0, 1, by=0.01)
plot(p32.VIs)

NDVI Parcela 3.2
cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p32.VIs$NDVI, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.2") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela3_2_NDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
MSAVI2 Parcela 3.2
cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p32.VIs$MSAVI2, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.1") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela3_2_MSAVI2.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
GNDVI Parcela 3.2
ggR(p32.VIs$GNDVI, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.2") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela3_2_GNDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
p33.VIs <- spectralIndices(ortho_p3.stack_p33, green = 3, red=2, nir =1, indices=c("NDVI", "MSAVI2", "GNDVI"))
breaks <- seq(0, 1, by=0.01)
plot(p33.VIs)

NDVI Parcela 3.3
cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p33.VIs$NDVI, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.3") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela3_3_NDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
MSAVI2 Parcela 3.3
cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p33.VIs$MSAVI2, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.3") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela3_3_MSAVI2.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
GNDVI Parcela 3.3
ggR(p33.VIs$GNDVI, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.3") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela3_3_GNDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
p34.VIs <- spectralIndices(ortho_p3.stack_p34, green = 3, red=2, nir =1, indices=c("NDVI", "MSAVI2", "GNDVI"))
breaks <- seq(0, 1, by=0.01)
plot(p34.VIs)

NDVI Parcela 3.4
cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p34.VIs$NDVI, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.4") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela3_4_NDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
MSAVI2 Parcela 3.4
cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p34.VIs$MSAVI2, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.4") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela3_4_MSAVI2.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
GNDVI Parcela 3.4
ggR(p34.VIs$GNDVI, geom_raster = TRUE) +
labs(x="", y="", title= "Parcela 3.4") +
scale_fill_gradientn(colours=cols, na.value=NA) +
theme_bw() +
theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela3_4_GNDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
Exploratory data analysis of Vegetation Indices
Manual approach to explore and plot NDVI
p31.VIs.NDVI.df <- stack(as.data.frame(p31.VIs$NDVI))
p31.VIs.NDVI.df$id <- rep("p31", length(p31.VIs.NDVI.df$ind))
p32.VIs.NDVI.df <- stack(as.data.frame(p32.VIs$NDVI))
p32.VIs.NDVI.df$id <- rep("p32", length(p32.VIs.NDVI.df$ind))
p33.VIs.NDVI.df <- stack(as.data.frame(p33.VIs$NDVI))
p33.VIs.NDVI.df$id <- rep("p33", length(p33.VIs.NDVI.df$ind))
p34.VIs.NDVI.df <- stack(as.data.frame(p34.VIs$NDVI))
p34.VIs.NDVI.df$id <- rep("p34", length(p34.VIs.NDVI.df$ind))
p3.VIs.NDVI <- rbind(p31.VIs.NDVI.df, p32.VIs.NDVI.df)
p3.VIs.NDVI <- rbind(p3.VIs.NDVI, p33.VIs.NDVI.df)
p3.VIs.NDVI <- rbind(p3.VIs.NDVI, p34.VIs.NDVI.df)
save(p3.VIs.NDVI, file = "data/p3_VIS_NDVI")
ggplot(p3.VIs.NDVI) +
geom_boxplot(aes(x = id, y = values, colour=id)) +
theme_bw()

Bind indices in a whole dataframe
library(dplyr)
Attaching package: 㤼㸱dplyr㤼㸲
The following objects are masked from 㤼㸱package:rgeos㤼㸲:
intersect, setdiff, union
The following objects are masked from 㤼㸱package:raster㤼㸲:
intersect, select, union
The following objects are masked from 㤼㸱package:stats㤼㸲:
filter, lag
The following objects are masked from 㤼㸱package:base㤼㸲:
intersect, setdiff, setequal, union
library(plyr) # Tools for Splitting, Applying and Combining Data
------------------------------------------------------------------------------------------------------------
You have loaded plyr after dplyr - this is likely to cause problems.
If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
library(plyr); library(dplyr)
------------------------------------------------------------------------------------------------------------
Attaching package: 㤼㸱plyr㤼㸲
The following objects are masked from 㤼㸱package:dplyr㤼㸲:
arrange, count, desc, failwith, id, mutate, rename, summarise, summarize
raster_to_df <- function(x) {
stack(as.data.frame(x))
} # convert raster to dataframe
l<- list(p31 = p31.VIs, p32 = p32.VIs, p33 = p33.VIs, p34 = p34.VIs)
l.df <- lapply(X = l, FUN = raster_to_df) # list of data frames
l.df.VIs <- ldply(l.df ,rbind) # Split list, apply function, and return results in a data frame.
Plot NDVI box-plot
l.df.VIs.NDVI <- subset(l.df.VIs, ind == "NDVI" )
ggplot(l.df.VIs.NDVI) +
geom_boxplot(aes(x = .id, y = values, colour=.id)) +
facet_grid(. ~ ind) +
theme_bw()

ggsave("figures/boxplot_p31_p32_p33_p34_NDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
Plot MSAVI2 box-plot
l.df.VIs.MSAVI2 <- subset(l.df.VIs, ind == "MSAVI2" )
ggplot(l.df.VIs.MSAVI2) +
geom_boxplot(aes(x = .id, y = values, colour=.id)) +
facet_grid(. ~ ind) +
theme_bw()

ggsave("figures/boxplot_p31_p32_p33_p34_MSAVI2.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
Plot GNDVI box-plot
l.df.VIs.GNDVI <- subset(l.df.VIs, ind == "GNDVI" )
ggplot(l.df.VIs.GNDVI) +
geom_boxplot(aes(x = .id, y = values, colour=.id)) +
facet_grid(. ~ ind) +
theme_bw()

ggsave("figures/boxplot_p31_p32_p33_p34_GNDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
Plot NDVI, GNDVI MSAVI2 histogram
l.df.VIs.NDVI$title <- "NDVI" # fake
ggplot(l.df.VIs.NDVI, aes(x = values, colour=.id)) +
geom_freqpoly(aes( y=(..count..)/sum(..count..)), binwidth = 0.005) +
facet_wrap(~title) +
scale_y_continuous(labels=scales::percent) +
ylab("relative frequencies") +
theme_bw()

ggsave("figures/histo_p31_p32_p33_p34_NDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
l.df.VIs.MSAVI2$title = "MSAVI2"
ggplot(l.df.VIs.MSAVI2, aes(x = values, colour=.id)) +
geom_freqpoly(aes( y=(..count..)/sum(..count..)), binwidth = 0.005) +
facet_wrap(~title) +
scale_y_continuous(labels=scales::percent) +
ylab("relative frequencies") +
theme_bw()

ggsave("figures/histo_p31_p32_p33_p34_MSAVI2.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
l.df.VIs.GNDVI$title <- "GNDVI" # fake
ggplot(l.df.VIs.GNDVI, aes(x = values, colour=.id)) +
geom_freqpoly(aes( y=(..count..)/sum(..count..)), binwidth = 0.005) +
facet_wrap(~title) +
scale_y_continuous(labels=scales::percent) +
ylab("relative frequencies") +
theme_bw()

ggsave("figures/histo_p31_p32_p33_p34_GNDVI.png",
plot = last_plot(), # or give ggplot object name as in myPlot,
width = 5, height = 5,
units = "in", # other options c("in", "cm", "mm"),
dpi = 300)
Analysis
library('dplyr')
l.df.VIs %>% group_by(ind) %>% summarise_at("values", funs(mean, max, sd), na.rm = TRUE)
library('dplyr')
l.df.VIs %>% group_by(ind, .id) %>% summarise_at("values", funs(mean, max, sd), na.rm = TRUE)
saveRDS(l.df.VIs, file = "VIP3.rds")
# save p41 layers
writeRaster(stack(p31.VIs), paste("p31_", names(p31.VIs), sep = ''), bylayer=TRUE, format='GTiff')
writeRaster(stack(p32.VIs), paste("p32_", names(p32.VIs), sep = ''), bylayer=TRUE, format='GTiff')
writeRaster(stack(p33.VIs), paste("p33_", names(p33.VIs), sep = ''), bylayer=TRUE, format='GTiff')
writeRaster(stack(p34.VIs), paste("p34_", names(p34.VIs), sep = ''), bylayer=TRUE, format='GTiff')
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCiMgcmVxdWlyZWQgbGlicmFyaWVzDQoNCmxpYnJhcnkoIlJTdG9vbGJveCIpDQpsaWJyYXJ5KCJyYXN0ZXIiKQ0KbGlicmFyeSgicmdkYWwiKQ0KbGlicmFyeSgiZ2dwbG90MiIpDQpsaWJyYXJ5KCJTRE1Ub29scyIpDQoNCmBgYA0KDQoNCg0KYGBge3J9DQojIGxvYWQgdGlmIHVzaW5nIHN0YWNrIGZ1bmN0aW9uIGluc3RlYWQgcmFzdGVyDQoNCm9ydGhvX3AzLnN0YWNrIDwtIHN0YWNrKCIuLi82X3FnaXMvb3V0cHV0L29ydGhvbW9zYWljX3BhcmNlbGEzX3Bob3Rvc2Nhbl9nZW9ycmVmZXJlbmNlZC50aWYiKQ0KY2xhc3Mob3J0aG9fcDMuc3RhY2spDQoNCmBgYA0KDQoNCg0KYGBge3J9DQojIGxvYWQgcGFyY2VsYSAxDQpsaWJyYXJ5KHJnZW9zKQ0KcGFyY2VsYXMgPC0gcmVhZE9HUigiLi4vNl9xZ2lzL2lucHV0L2FsYW1hbGEua21sIiwgImFsYW1hbGEiKVswXQ0KbnJvd2RpbSA8LSBkaW0ocGFyY2VsYXNAZGF0YSkNCnBhcmNlbGFzQGRhdGEkaWQgPC0gYyhyZXAoMTpucm93ZGltKSkNCnBhcmNlbGEzIDwtIHN1YnNldChwYXJjZWxhcywgcGFyY2VsYXNAZGF0YSRpZCAlaW4lIGMoOSwxMCwgMTEsIDEyKSkNCnAzLmNlbnRyb2lkLmRmIDwtIGFzLmRhdGEuZnJhbWUoZ0NlbnRyb2lkKHBhcmNlbGEzLCBieWlkID0gVFJVRSkpICMgZXh0cmFjdCB0byBsYWJlbCBwYXJjZWxzDQpjbGFzcyhwYXJjZWxhMykNCnBsb3QocGFyY2VsYTMpDQoNCmBgYA0KDQpgYGB7cn0NCnBhcmNlbGEzLmRmIDwtIGZvcnRpZnkocGFyY2VsYTMpICMgdG8gcGxvdCB3aXRoIGdncGxvdA0KaGVhZChwYXJjZWxhMy5kZikNCmBgYA0KDQpgYGB7cn0NCg0KDQojIFNldCBhbGwgcGl4ZWxzIHRvIE5BLCB3aGVyZSBiYW5kcyBhcmUgMCAocmVtb3ZlIGJsYWNrIGJhY2tncm91bmQpDQojIENoZWNrIGlmIHJlc3VsdHMgYXJlIGFmZmVjdGVkDQojIGluc3RlYWQgdXNlIGNyb3AgYW5kIG1hc2sgdG9nZXRoZXIgKHZlciBtw6FzIGFkZWxhbnRlKQ0KDQpvcnRob19wMy5zdGFja1tvcnRob19wMy5zdGFja1ssXSA9PSAwXSA8LSBOQQ0KDQoNCiMgcGxvdCBzY2VuZSB1c2luZyBnZ1JHQiAoZnJvbSBnZ3Bsb3QgYW5kIFJTdG9vbGJveCkNCmdnUkdCKG9ydGhvX3AzLnN0YWNrLCByID0gMSwgZyA9IDIsIGIgPSAzLCBtYXhwaXhlbHMgPSAyZSswNSwgc3RyZXRjaD0ibm9uZSIsIGdlb21fcmFzdGVyID0gVFJVRSkgKyANCiAgICBnZW9tX3BhdGgoZGF0YSA9IHBhcmNlbGEzLmRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBzaXplID0gMSwgY29sPSIjZmJhZTNiIikgKw0KICAgIGdlb21fdGV4dChkYXRhID0gcDMuY2VudHJvaWQuZGYsIGFlcyhsYWJlbCA9IGMoIjMuMSIsICIzLjIiLCAiMy4zIiwgIjMuNCIpICx5ID0geSwgeCA9IHggKyAwLjAwMDIpLCBjb2xvdXIgPSAid2hpdGUiKSArDQogICAgY29vcmRfZXF1YWwoKSArDQogICAgdGhlbWVfYncoKQ0KYGBgDQoNCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTMucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQoNCkV4dHJhZW1vcyBsYXMgcGFyY2VsYXMNCg0KYGBge3J9DQojIGNyb3AgYW5kIG1hc2sgd2hvbGUgYXJlYQ0KDQpvcnRob19wMy5zdGFja19wMyA8LSBjcm9wKG1hc2sob3J0aG9fcDMuc3RhY2ssIHBhcmNlbGEzKSxwYXJjZWxhMykNCg0KYGBgDQoNCg0KYGBge3J9DQoNCiMgY3JvcCBwYXJjZWxhIDMuMQ0KDQpwYXJjZWxhMzEgPC0gc3Vic2V0KHBhcmNlbGFzLCBwYXJjZWxhc0BkYXRhJGlkICVpbiUgYyg5KSkNCm9ydGhvX3AzLnN0YWNrX3AzMSA8LSBjcm9wKG1hc2sob3J0aG9fcDMuc3RhY2tfcDMsIHBhcmNlbGEzMSksIHBhcmNlbGEzMSkNCiANCiMgY3JvcCBwYXJjZWxhIDEuMg0KcGFyY2VsYTMyIDwtIHN1YnNldChwYXJjZWxhcywgcGFyY2VsYXNAZGF0YSRpZCAlaW4lIGMoMTApKQ0KDQpvcnRob19wMy5zdGFja19wMzIgPC0gY3JvcChtYXNrKG9ydGhvX3AzLnN0YWNrX3AzLCBwYXJjZWxhMzIpLCBwYXJjZWxhMzIpDQoNCiMgY3JvcCBwYXJjZWxhIDEuMg0KcGFyY2VsYTMzIDwtIHN1YnNldChwYXJjZWxhcywgcGFyY2VsYXNAZGF0YSRpZCAlaW4lIGMoMTEpKQ0KDQpvcnRob19wMy5zdGFja19wMzMgPC0gY3JvcChtYXNrKG9ydGhvX3AzLnN0YWNrX3AzLCBwYXJjZWxhMzMpLCBwYXJjZWxhMzMpDQoNCg0KIyBjcm9wIHBhcmNlbGEgMS4yDQpwYXJjZWxhMzQgPC0gc3Vic2V0KHBhcmNlbGFzLCBwYXJjZWxhc0BkYXRhJGlkICVpbiUgYygxMikpDQoNCm9ydGhvX3AzLnN0YWNrX3AzNCA8LSBjcm9wKG1hc2sob3J0aG9fcDMuc3RhY2tfcDMsIHBhcmNlbGEzNCksIHBhcmNlbGEzNCkNCg0KDQpgYGANCg0KUGxvdCBwYXJjZWxzDQoNCmBgYHtyfQ0KDQpnZ1JHQihvcnRob19wMy5zdGFja19wMywgciA9IDEsIGcgPSAyLCBiID0gMykgKyANCiAgICBnZW9tX3BhdGgoZGF0YSA9IHBhcmNlbGEzLmRmLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBzaXplID0gMSwgY29sPSIjZmJhZTNiIikgKw0KICAgIHRoZW1lX2J3KCkNCmBgYA0KDQoNClBsb3QgcGFyY2VsIDMuMQ0KDQpgYGB7cn0NCnAzMSA8LSBzdWJzZXQocGFyY2VsYTMuZGYsIGlkID09IDgpDQoNCmdnUkdCKG9ydGhvX3AzLnN0YWNrX3AzMSwgciA9IDEsIGcgPSAyLCBiID0gMykgKyANCiAgICBnZW9tX3BhdGgoZGF0YSA9IHAzMSwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgc2l6ZSA9IDEsIGNvbD0iI2ZiYWUzYiIpICsNCiAgICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSJQYXJjZWxhIDMuMSIpICsNCiAgICMgY29vcmRfZXF1YWwoeWxpbSA9IGMobWluKHAxMSRsYXQpLCBtYXgocDExJGxhdCkpLCB4bGltPSBjKG1pbihwMTEkbG9uZyksIG1heChwMTEkbG9uZykpKSArDQogICAgdGhlbWVfYncoKSArIA0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkgICMgbWFrZSB0aXRsZSBib2xkIGFuZCBhZGQgc3BhYw0KDQpgYGANCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGEzXzEucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQoNCmBgYHtyfQ0KZ2dSR0Iob3J0aG9fcDMuc3RhY2ssIHIgPSAxLCBnID0gMiwgYiA9IDMpICsgDQogICAgZ2VvbV9wYXRoKGRhdGEgPSBwMzEsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIHNpemUgPSAxLCBjb2w9IiNmYmFlM2IiKSArDQogICAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0iUGFyY2VsYSAzLjEiKSArDQogICAjIGNvb3JkX2VxdWFsKHlsaW0gPSBjKG1pbihwMTEkbGF0KSwgbWF4KHAxMSRsYXQpKSwgeGxpbT0gYyhtaW4ocDExJGxvbmcpLCBtYXgocDExJGxvbmcpKSkgKw0KICAgIHRoZW1lX2J3KCkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpICAjIG1ha2UgdGl0bGUgYm9sZCBhbmQgYWRkIHNwYWMNCg0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGEzXzFfb3J0aG8ucGRmIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQpQbG90IHBhcmNlbCAzLjINCg0KYGBge3J9DQpwMzIgPC0gc3Vic2V0KHBhcmNlbGEzLmRmLCBpZCA9PSA5KQ0KDQpnZ1JHQihvcnRob19wMy5zdGFja19wMzIsIHIgPSAxLCBnID0gMiwgYiA9IDMpICsgDQogICAgZ2VvbV9wYXRoKGRhdGEgPSBwMzIsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIHNpemUgPSAxLCBjb2w9IiNmYmFlM2IiKSArDQogICAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0iUGFyY2VsYSAzLjIiKSArDQogICAjIGNvb3JkX2VxdWFsKHlsaW0gPSBjKG1pbihwMTEkbGF0KSwgbWF4KHAxMSRsYXQpKSwgeGxpbT0gYyhtaW4ocDExJGxvbmcpLCBtYXgocDExJGxvbmcpKSkgKw0KICAgIHRoZW1lX2J3KCkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpICAjIG1ha2UgdGl0bGUgYm9sZCBhbmQgYWRkIHNwYWMNCg0KYGBgDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhM18yLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KDQoNCmBgYHtyfQ0KZ2dSR0Iob3J0aG9fcDMuc3RhY2ssIHIgPSAxLCBnID0gMiwgYiA9IDMpICsgDQogICAgZ2VvbV9wYXRoKGRhdGEgPSBwMzIsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIHNpemUgPSAxLCBjb2w9IiNmYmFlM2IiKSArDQogICAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0iUGFyY2VsYSAzLjIiKSArDQogICAjIGNvb3JkX2VxdWFsKHlsaW0gPSBjKG1pbihwMTEkbGF0KSwgbWF4KHAxMSRsYXQpKSwgeGxpbT0gYyhtaW4ocDExJGxvbmcpLCBtYXgocDExJGxvbmcpKSkgKw0KICAgIHRoZW1lX2J3KCkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpICAjIG1ha2UgdGl0bGUgYm9sZCBhbmQgYWRkIHNwYWMNCg0KYGBgDQoNCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTNfMl9vcnRoby5wZGYiLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCg0KUGxvdCBwYXJjZWwgMy4zDQoNCmBgYHtyfQ0KcDMzIDwtIHN1YnNldChwYXJjZWxhMy5kZiwgaWQgPT0gMTApDQoNCmdnUkdCKG9ydGhvX3AzLnN0YWNrX3AzMywgciA9IDEsIGcgPSAyLCBiID0gMykgKyANCiAgICBnZW9tX3BhdGgoZGF0YSA9IHAzMywgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgc2l6ZSA9IDEsIGNvbD0iI2ZiYWUzYiIpICsNCiAgICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSJQYXJjZWxhIDMuMyIpICsNCiAgICMgY29vcmRfZXF1YWwoeWxpbSA9IGMobWluKHAxMSRsYXQpLCBtYXgocDExJGxhdCkpLCB4bGltPSBjKG1pbihwMTEkbG9uZyksIG1heChwMTEkbG9uZykpKSArDQogICAgdGhlbWVfYncoKSArIA0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkgICMgbWFrZSB0aXRsZSBib2xkIGFuZCBhZGQgc3BhYw0KDQpgYGANCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGEzXzMucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQoNCg0KDQpgYGB7cn0NCmdnUkdCKG9ydGhvX3AzLnN0YWNrLCByID0gMSwgZyA9IDIsIGIgPSAzKSArIA0KICAgIGdlb21fcGF0aChkYXRhID0gcDMzLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBzaXplID0gMSwgY29sPSIjZmJhZTNiIikgKw0KICAgIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9IlBhcmNlbGEgMy4yIikgKw0KICAgIyBjb29yZF9lcXVhbCh5bGltID0gYyhtaW4ocDExJGxhdCksIG1heChwMTEkbGF0KSksIHhsaW09IGMobWluKHAxMSRsb25nKSwgbWF4KHAxMSRsb25nKSkpICsNCiAgICB0aGVtZV9idygpICsgDQogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIiwgdmp1c3Q9MSwgaGp1c3QgPSAwLjUpKSAgIyBtYWtlIHRpdGxlIGJvbGQgYW5kIGFkZCBzcGFjDQoNCmBgYA0KDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGEzXzNfb3J0aG8ucGRmIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQoNClBsb3QgcGFyY2VsIDMuNA0KDQpgYGB7cn0NCnAzNCA8LSBzdWJzZXQocGFyY2VsYTMuZGYsIGlkID09IDExKQ0KDQpnZ1JHQihvcnRob19wMy5zdGFja19wMzQsIHIgPSAxLCBnID0gMiwgYiA9IDMpICsgDQogICAgZ2VvbV9wYXRoKGRhdGEgPSBwMzQsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIHNpemUgPSAxLCBjb2w9IiNmYmFlM2IiKSArDQogICAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0iUGFyY2VsYSAzLjQiKSArDQogICAjIGNvb3JkX2VxdWFsKHlsaW0gPSBjKG1pbihwMTEkbGF0KSwgbWF4KHAxMSRsYXQpKSwgeGxpbT0gYyhtaW4ocDExJGxvbmcpLCBtYXgocDExJGxvbmcpKSkgKw0KICAgIHRoZW1lX2J3KCkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpICAjIG1ha2UgdGl0bGUgYm9sZCBhbmQgYWRkIHNwYWMNCg0KYGBgDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhM180LnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KDQpgYGB7cn0NCmdnUkdCKG9ydGhvX3AzLnN0YWNrLCByID0gMSwgZyA9IDIsIGIgPSAzKSArIA0KICAgIGdlb21fcGF0aChkYXRhID0gcDM0LCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBzaXplID0gMSwgY29sPSIjZmJhZTNiIikgKw0KICAgIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9IlBhcmNlbGEgMy40IikgKw0KICAgIyBjb29yZF9lcXVhbCh5bGltID0gYyhtaW4ocDExJGxhdCksIG1heChwMTEkbGF0KSksIHhsaW09IGMobWluKHAxMSRsb25nKSwgbWF4KHAxMSRsb25nKSkpICsNCiAgICB0aGVtZV9idygpICsgDQogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIiwgdmp1c3Q9MSwgaGp1c3QgPSAwLjUpKSAgIyBtYWtlIHRpdGxlIGJvbGQgYW5kIGFkZCBzcGFjDQoNCmBgYA0KDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGEzXzRfb3J0aG8ucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQoNCg0KQ2FsY3VsYXRlIFZJcw0KDQpgYGB7cn0NCg0KcDMxLlZJcyA8LSBzcGVjdHJhbEluZGljZXMob3J0aG9fcDMuc3RhY2tfcDMxLCBncmVlbiA9IDMsIHJlZD0yLCBuaXIgPTEsIGluZGljZXM9YygiTkRWSSIsICJNU0FWSTIiLCAiR05EVkkiKSkNCmJyZWFrcyA8LSBzZXEoMCwgMSwgYnk9MC4wMSkNCg0KcGxvdChwMzEuVklzKQ0KYGBgDQpQbG90IFZJIG9uZSBieSBvbmUNCg0KDQpORFZJIFBhcmNlbGEgMy4xDQoNCmBgYHtyfQ0KY29scyA8LSBjb2xvclJhbXBQYWxldHRlKGMoInJlZCIsICJ5ZWxsb3ciLCAibGlnaHRncmVlbiIpKShsZW5ndGgoYnJlYWtzKS0xKQ0KZ2dSKHAzMS5WSXMkTkRWSSwgZ2VvbV9yYXN0ZXIgPSBUUlVFKSArDQogIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9ICJQYXJjZWxhIDMuMSIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz1jb2xzLCAgbmEudmFsdWU9TkEpICsgDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpDQoNCmBgYA0KQW5kIHNhdmUNCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTNfMV9ORFZJLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KDQpNU0FWSTIgUGFyY2VsYSAzLjENCg0KYGBge3J9DQpjb2xzIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygicmVkIiwgInllbGxvdyIsICJsaWdodGdyZWVuIikpKGxlbmd0aChicmVha3MpLTEpDQpnZ1IocDMxLlZJcyRNU0FWSTIsIGdlb21fcmFzdGVyID0gVFJVRSkgKw0KICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSAiUGFyY2VsYSAzLjEiKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnM9Y29scywgIG5hLnZhbHVlPU5BKSArIA0KICB0aGVtZV9idygpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIiwgdmp1c3Q9MSwgaGp1c3QgPSAwLjUpKQ0KDQpgYGANCkFuZCBzYXZlDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGEzXzFfTVNBVkkyLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KDQpHTkRWSSBQYXJjZWxhIDEuMQ0KDQpgYGB7cn0NCmdnUihwMzEuVklzJEdORFZJLCBnZW9tX3Jhc3RlciA9IFRSVUUpICsNCiAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0gIlBhcmNlbGEgMy4xIikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPWNvbHMsICBuYS52YWx1ZT1OQSkgKyANCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkNCg0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGEzXzFfR05EVkkucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQoNCmBgYHtyfQ0KDQpwMzIuVklzIDwtIHNwZWN0cmFsSW5kaWNlcyhvcnRob19wMy5zdGFja19wMzIsIGdyZWVuID0gMywgcmVkPTIsIG5pciA9MSwgaW5kaWNlcz1jKCJORFZJIiwgIk1TQVZJMiIsICJHTkRWSSIpKQ0KYnJlYWtzIDwtIHNlcSgwLCAxLCBieT0wLjAxKQ0KDQpwbG90KHAzMi5WSXMpDQpgYGANCg0KTkRWSSBQYXJjZWxhIDMuMg0KDQpgYGB7cn0NCmNvbHMgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJyZWQiLCAieWVsbG93IiwgImxpZ2h0Z3JlZW4iKSkobGVuZ3RoKGJyZWFrcyktMSkNCmdnUihwMzIuVklzJE5EVkksIGdlb21fcmFzdGVyID0gVFJVRSkgKw0KICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSAiUGFyY2VsYSAzLjIiKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnM9Y29scywgIG5hLnZhbHVlPU5BKSArIA0KICB0aGVtZV9idygpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIiwgdmp1c3Q9MSwgaGp1c3QgPSAwLjUpKQ0KDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTNfMl9ORFZJLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KTVNBVkkyIFBhcmNlbGEgMy4yDQoNCmBgYHtyfQ0KY29scyA8LSBjb2xvclJhbXBQYWxldHRlKGMoInJlZCIsICJ5ZWxsb3ciLCAibGlnaHRncmVlbiIpKShsZW5ndGgoYnJlYWtzKS0xKQ0KZ2dSKHAzMi5WSXMkTVNBVkkyLCBnZW9tX3Jhc3RlciA9IFRSVUUpICsNCiAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0gIlBhcmNlbGEgMy4xIikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPWNvbHMsICBuYS52YWx1ZT1OQSkgKyANCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkNCg0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGEzXzJfTVNBVkkyLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KR05EVkkgUGFyY2VsYSAzLjINCg0KYGBge3J9DQpnZ1IocDMyLlZJcyRHTkRWSSwgZ2VvbV9yYXN0ZXIgPSBUUlVFKSArDQogIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9ICJQYXJjZWxhIDMuMiIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz1jb2xzLCAgbmEudmFsdWU9TkEpICsgDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpDQoNCmBgYA0KDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhM18yX0dORFZJLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KYGBge3J9DQoNCnAzMy5WSXMgPC0gc3BlY3RyYWxJbmRpY2VzKG9ydGhvX3AzLnN0YWNrX3AzMywgZ3JlZW4gPSAzLCByZWQ9MiwgbmlyID0xLCBpbmRpY2VzPWMoIk5EVkkiLCAiTVNBVkkyIiwgIkdORFZJIikpDQpicmVha3MgPC0gc2VxKDAsIDEsIGJ5PTAuMDEpDQoNCnBsb3QocDMzLlZJcykNCmBgYA0KDQpORFZJIFBhcmNlbGEgMy4zDQoNCmBgYHtyfQ0KY29scyA8LSBjb2xvclJhbXBQYWxldHRlKGMoInJlZCIsICJ5ZWxsb3ciLCAibGlnaHRncmVlbiIpKShsZW5ndGgoYnJlYWtzKS0xKQ0KZ2dSKHAzMy5WSXMkTkRWSSwgZ2VvbV9yYXN0ZXIgPSBUUlVFKSArDQogIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9ICJQYXJjZWxhIDMuMyIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz1jb2xzLCAgbmEudmFsdWU9TkEpICsgDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpDQoNCmBgYA0KDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhM18zX05EVkkucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQpNU0FWSTIgUGFyY2VsYSAzLjMNCg0KYGBge3J9DQpjb2xzIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygicmVkIiwgInllbGxvdyIsICJsaWdodGdyZWVuIikpKGxlbmd0aChicmVha3MpLTEpDQpnZ1IocDMzLlZJcyRNU0FWSTIsIGdlb21fcmFzdGVyID0gVFJVRSkgKw0KICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSAiUGFyY2VsYSAzLjMiKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnM9Y29scywgIG5hLnZhbHVlPU5BKSArIA0KICB0aGVtZV9idygpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIiwgdmp1c3Q9MSwgaGp1c3QgPSAwLjUpKQ0KDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTNfM19NU0FWSTIucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQpHTkRWSSBQYXJjZWxhIDMuMw0KDQpgYGB7cn0NCmdnUihwMzMuVklzJEdORFZJLCBnZW9tX3Jhc3RlciA9IFRSVUUpICsNCiAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0gIlBhcmNlbGEgMy4zIikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPWNvbHMsICBuYS52YWx1ZT1OQSkgKyANCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkNCg0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGEzXzNfR05EVkkucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQpgYGB7cn0NCg0KcDM0LlZJcyA8LSBzcGVjdHJhbEluZGljZXMob3J0aG9fcDMuc3RhY2tfcDM0LCBncmVlbiA9IDMsIHJlZD0yLCBuaXIgPTEsIGluZGljZXM9YygiTkRWSSIsICJNU0FWSTIiLCAiR05EVkkiKSkNCmJyZWFrcyA8LSBzZXEoMCwgMSwgYnk9MC4wMSkNCg0KcGxvdChwMzQuVklzKQ0KYGBgDQoNCk5EVkkgUGFyY2VsYSAzLjQNCg0KYGBge3J9DQpjb2xzIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygicmVkIiwgInllbGxvdyIsICJsaWdodGdyZWVuIikpKGxlbmd0aChicmVha3MpLTEpDQpnZ1IocDM0LlZJcyRORFZJLCBnZW9tX3Jhc3RlciA9IFRSVUUpICsNCiAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0gIlBhcmNlbGEgMy40IikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPWNvbHMsICBuYS52YWx1ZT1OQSkgKyANCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkNCg0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGEzXzRfTkRWSS5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCk1TQVZJMiBQYXJjZWxhIDMuNA0KDQpgYGB7cn0NCmNvbHMgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJyZWQiLCAieWVsbG93IiwgImxpZ2h0Z3JlZW4iKSkobGVuZ3RoKGJyZWFrcyktMSkNCmdnUihwMzQuVklzJE1TQVZJMiwgZ2VvbV9yYXN0ZXIgPSBUUlVFKSArDQogIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9ICJQYXJjZWxhIDMuNCIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz1jb2xzLCAgbmEudmFsdWU9TkEpICsgDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpDQoNCmBgYA0KDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhM180X01TQVZJMi5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCkdORFZJIFBhcmNlbGEgMy40DQoNCmBgYHtyfQ0KZ2dSKHAzNC5WSXMkR05EVkksIGdlb21fcmFzdGVyID0gVFJVRSkgKw0KICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSAiUGFyY2VsYSAzLjQiKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnM9Y29scywgIG5hLnZhbHVlPU5BKSArIA0KICB0aGVtZV9idygpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIiwgdmp1c3Q9MSwgaGp1c3QgPSAwLjUpKQ0KDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTNfNF9HTkRWSS5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCg0KIyMjIEV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgb2YgVmVnZXRhdGlvbiBJbmRpY2VzDQoNCg0KTWFudWFsIGFwcHJvYWNoIHRvIGV4cGxvcmUgYW5kIHBsb3QgTkRWSQ0KDQpgYGB7cn0NCnAzMS5WSXMuTkRWSS5kZiA8LSBzdGFjayhhcy5kYXRhLmZyYW1lKHAzMS5WSXMkTkRWSSkpDQpwMzEuVklzLk5EVkkuZGYkaWQgPC0gcmVwKCJwMzEiLCBsZW5ndGgocDMxLlZJcy5ORFZJLmRmJGluZCkpDQoNCnAzMi5WSXMuTkRWSS5kZiA8LSBzdGFjayhhcy5kYXRhLmZyYW1lKHAzMi5WSXMkTkRWSSkpDQpwMzIuVklzLk5EVkkuZGYkaWQgPC0gcmVwKCJwMzIiLCBsZW5ndGgocDMyLlZJcy5ORFZJLmRmJGluZCkpIA0KDQpwMzMuVklzLk5EVkkuZGYgPC0gc3RhY2soYXMuZGF0YS5mcmFtZShwMzMuVklzJE5EVkkpKQ0KcDMzLlZJcy5ORFZJLmRmJGlkIDwtIHJlcCgicDMzIiwgbGVuZ3RoKHAzMy5WSXMuTkRWSS5kZiRpbmQpKSANCg0KcDM0LlZJcy5ORFZJLmRmIDwtIHN0YWNrKGFzLmRhdGEuZnJhbWUocDM0LlZJcyRORFZJKSkNCnAzNC5WSXMuTkRWSS5kZiRpZCA8LSByZXAoInAzNCIsIGxlbmd0aChwMzQuVklzLk5EVkkuZGYkaW5kKSkgDQoNCnAzLlZJcy5ORFZJIDwtIHJiaW5kKHAzMS5WSXMuTkRWSS5kZiwgcDMyLlZJcy5ORFZJLmRmKQ0KcDMuVklzLk5EVkkgPC0gcmJpbmQocDMuVklzLk5EVkksIHAzMy5WSXMuTkRWSS5kZikNCnAzLlZJcy5ORFZJIDwtIHJiaW5kKHAzLlZJcy5ORFZJLCBwMzQuVklzLk5EVkkuZGYpDQoNCnNhdmUocDMuVklzLk5EVkksIGZpbGUgPSAiZGF0YS9wM19WSVNfTkRWSSIpDQoNCmBgYA0KDQoNCg0KYGBge3J9DQpnZ3Bsb3QocDMuVklzLk5EVkkpICsgDQogIGdlb21fYm94cGxvdChhZXMoeCA9IGlkLCB5ID0gdmFsdWVzLCBjb2xvdXI9aWQpKSArDQogIHRoZW1lX2J3KCkgDQoNCmBgYA0KDQpCaW5kIGluZGljZXMgaW4gYSB3aG9sZSBkYXRhZnJhbWUNCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwbHlyKSAjIFRvb2xzIGZvciBTcGxpdHRpbmcsIEFwcGx5aW5nIGFuZCBDb21iaW5pbmcgRGF0YQ0KDQpyYXN0ZXJfdG9fZGYgPC0gZnVuY3Rpb24oeCkgew0KICBzdGFjayhhcy5kYXRhLmZyYW1lKHgpKQ0KfSAjIGNvbnZlcnQgcmFzdGVyIHRvIGRhdGFmcmFtZQ0KDQoNCmw8LSBsaXN0KHAzMSA9IHAzMS5WSXMsIHAzMiA9IHAzMi5WSXMsIHAzMyA9IHAzMy5WSXMsIHAzNCA9IHAzNC5WSXMpDQoNCmwuZGYgPC0gbGFwcGx5KFggPSBsLCBGVU4gPSByYXN0ZXJfdG9fZGYpICMgbGlzdCBvZiBkYXRhIGZyYW1lcw0KDQoNCmwuZGYuVklzIDwtIGxkcGx5KGwuZGYgLHJiaW5kKSAjIFNwbGl0IGxpc3QsIGFwcGx5IGZ1bmN0aW9uLCBhbmQgcmV0dXJuIHJlc3VsdHMgaW4gYSBkYXRhIGZyYW1lLg0KDQoNCmBgYA0KDQoNClBsb3QgTkRWSSBib3gtcGxvdA0KDQpgYGB7cn0NCmwuZGYuVklzLk5EVkkgPC0gIHN1YnNldChsLmRmLlZJcywgaW5kID09ICJORFZJIiApDQpnZ3Bsb3QobC5kZi5WSXMuTkRWSSkgKyANCiAgZ2VvbV9ib3hwbG90KGFlcyh4ID0gLmlkLCB5ID0gdmFsdWVzLCBjb2xvdXI9LmlkKSkgKw0KICBmYWNldF9ncmlkKC4gfiBpbmQpICsNCiAgdGhlbWVfYncoKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL2JveHBsb3RfcDMxX3AzMl9wMzNfcDM0X05EVkkucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQpQbG90IE1TQVZJMiBib3gtcGxvdA0KDQoNCmBgYHtyfQ0KbC5kZi5WSXMuTVNBVkkyIDwtICBzdWJzZXQobC5kZi5WSXMsIGluZCA9PSAiTVNBVkkyIiApDQpnZ3Bsb3QobC5kZi5WSXMuTVNBVkkyKSArIA0KICBnZW9tX2JveHBsb3QoYWVzKHggPSAuaWQsIHkgPSB2YWx1ZXMsIGNvbG91cj0uaWQpKSArDQogIGZhY2V0X2dyaWQoLiB+IGluZCkgKw0KICB0aGVtZV9idygpDQpgYGANCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL2JveHBsb3RfcDMxX3AzMl9wMzNfcDM0X01TQVZJMi5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNClBsb3QgR05EVkkgYm94LXBsb3QNCg0KDQpgYGB7cn0NCmwuZGYuVklzLkdORFZJIDwtICBzdWJzZXQobC5kZi5WSXMsIGluZCA9PSAiR05EVkkiICkNCmdncGxvdChsLmRmLlZJcy5HTkRWSSkgKyANCiAgZ2VvbV9ib3hwbG90KGFlcyh4ID0gLmlkLCB5ID0gdmFsdWVzLCBjb2xvdXI9LmlkKSkgKw0KICBmYWNldF9ncmlkKC4gfiBpbmQpICsNCiAgdGhlbWVfYncoKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL2JveHBsb3RfcDMxX3AzMl9wMzNfcDM0X0dORFZJLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KDQpQbG90IE5EVkksIEdORFZJIE1TQVZJMiBoaXN0b2dyYW0NCg0KYGBge3J9DQoNCmwuZGYuVklzLk5EVkkkdGl0bGUgPC0gIk5EVkkiICMgZmFrZQ0KDQpnZ3Bsb3QobC5kZi5WSXMuTkRWSSwgYWVzKHggPSB2YWx1ZXMsIGNvbG91cj0uaWQpKSArIA0KICBnZW9tX2ZyZXFwb2x5KGFlcyggeT0oLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSksIGJpbndpZHRoID0gMC4wMDUpICsNCiAgZmFjZXRfd3JhcCh+dGl0bGUpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsNCiAgeWxhYigicmVsYXRpdmUgZnJlcXVlbmNpZXMiKSArIA0KICB0aGVtZV9idygpDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvaGlzdG9fcDMxX3AzMl9wMzNfcDM0X05EVkkucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQpgYGB7cn0NCg0KbC5kZi5WSXMuTVNBVkkyJHRpdGxlID0gIk1TQVZJMiINCg0KZ2dwbG90KGwuZGYuVklzLk1TQVZJMiwgYWVzKHggPSB2YWx1ZXMsIGNvbG91cj0uaWQpKSArIA0KICBnZW9tX2ZyZXFwb2x5KGFlcyggeT0oLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSksIGJpbndpZHRoID0gMC4wMDUpICsNCiAgZmFjZXRfd3JhcCh+dGl0bGUpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsNCiAgeWxhYigicmVsYXRpdmUgZnJlcXVlbmNpZXMiKSArIA0KICB0aGVtZV9idygpDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvaGlzdG9fcDMxX3AzMl9wMzNfcDM0X01TQVZJMi5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCmBgYHtyfQ0KbC5kZi5WSXMuR05EVkkkdGl0bGUgPC0gIkdORFZJIiAjIGZha2UNCg0KDQpnZ3Bsb3QobC5kZi5WSXMuR05EVkksIGFlcyh4ID0gdmFsdWVzLCBjb2xvdXI9LmlkKSkgKyANCiAgZ2VvbV9mcmVxcG9seShhZXMoIHk9KC4uY291bnQuLikvc3VtKC4uY291bnQuLikpLCBiaW53aWR0aCA9IDAuMDA1KSArDQogIGZhY2V0X3dyYXAofnRpdGxlKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArDQogIHlsYWIoInJlbGF0aXZlIGZyZXF1ZW5jaWVzIikgKyANCiAgdGhlbWVfYncoKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL2hpc3RvX3AzMV9wMzJfcDMzX3AzNF9HTkRWSS5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCg0KIyBBbmFseXNpcw0KDQpgYGB7cn0NCmxpYnJhcnkoJ2RwbHlyJykNCmwuZGYuVklzICU+JSBncm91cF9ieShpbmQpICU+JSBzdW1tYXJpc2VfYXQoInZhbHVlcyIsIGZ1bnMobWVhbiwgbWF4LCBzZCksIG5hLnJtID0gVFJVRSkNCg0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeSgnZHBseXInKQ0KbC5kZi5WSXMgJT4lIGdyb3VwX2J5KGluZCwgLmlkKSAlPiUgc3VtbWFyaXNlX2F0KCJ2YWx1ZXMiLCBmdW5zKG1lYW4sIG1heCwgc2QpLCBuYS5ybSA9IFRSVUUpDQpgYGANCg0KYGBge3J9DQpzYXZlUkRTKGwuZGYuVklzLCBmaWxlID0gIlZJUDMucmRzIikNCmBgYA0KDQoNCg0KYGBge3J9DQojIHNhdmUgcDQxIGxheWVycw0Kd3JpdGVSYXN0ZXIoc3RhY2socDMxLlZJcyksIHBhc3RlKCJwMzFfIiwgbmFtZXMocDMxLlZJcyksIHNlcCA9ICcnKSwgYnlsYXllcj1UUlVFLCBmb3JtYXQ9J0dUaWZmJykNCndyaXRlUmFzdGVyKHN0YWNrKHAzMi5WSXMpLCBwYXN0ZSgicDMyXyIsIG5hbWVzKHAzMi5WSXMpLCBzZXAgPSAnJyksIGJ5bGF5ZXI9VFJVRSwgZm9ybWF0PSdHVGlmZicpDQp3cml0ZVJhc3RlcihzdGFjayhwMzMuVklzKSwgcGFzdGUoInAzM18iLCBuYW1lcyhwMzMuVklzKSwgc2VwID0gJycpLCBieWxheWVyPVRSVUUsIGZvcm1hdD0nR1RpZmYnKQ0Kd3JpdGVSYXN0ZXIoc3RhY2socDM0LlZJcyksIHBhc3RlKCJwMzRfIiwgbmFtZXMocDM0LlZJcyksIHNlcCA9ICcnKSwgYnlsYXllcj1UUlVFLCBmb3JtYXQ9J0dUaWZmJykNCg0KYGBgDQo=